﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Threading.Tasks;
using DwgSearchView.Models;

namespace DwgSearchView.Helpers
{
    /// <summary>
    /// 
    /// </summary>
    public class CDrawingDataHelper
    {
        #region Err

        #endregion

        #region Const

        /// <summary>
        /// 图纸数据存储文件相对路径
        /// </summary>
        private string CONST_DRAWING_DATA_FILE_PATH = @"data\XDrawingData.xml";

        /// <summary>
        /// 元素（节点）名称
        /// </summary>
        private string CONST_ELE_NAME_DRAWINGS = "Drawings";
        private string CONST_ELE_NAME_DRAWING = "Drawing";

        /// <summary>
        /// 图纸元素（节点）的属性名称
        /// </summary>
        private string CONST_DRAWING_ELE_ATTR_NAME_ID = "id";
        private string CONST_DRAWING_ELE_ATTR_NAME_TOOLINGNO = "toolingNo";
        private string CONST_DRAWING_ELE_ATTR_NAME_TYPE = "type";
        private string CONST_DRAWING_ELE_ATTR_NAME_PARTNO = "partNo";
        private string CONST_DRAWING_ELE_ATTR_NAME_PARTNAME = "partName";
        private string CONST_DRAWING_ELE_ATTR_NAME_PROCESSNAME = "processName";
        private string CONST_DRAWING_ELE_ATTR_NAME_FILEPATH = "filePath";

        #endregion

        #region Fields

        /// <summary>
        /// 图纸数据存储文件路径
        /// </summary>
        private string m_strDrawingDataFilePath = string.Empty;
        public string DrawingDataFilePath
        {
            get { return m_strDrawingDataFilePath; }
        }

        #endregion

        #region Construction

        private readonly static CDrawingDataHelper m_oInstance = new CDrawingDataHelper();
        public static CDrawingDataHelper Instance
        {
            get { return m_oInstance; }
        }

        private CDrawingDataHelper()
        {
            m_strDrawingDataFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, CONST_DRAWING_DATA_FILE_PATH);
        }

        #endregion

        #region Public Function

        /// <summary>
        /// 添加图纸信息数据
        /// </summary>
        /// <param name="lstDrawing">图纸信息对象集</param>
        public void AddDrawingDatas(List<CDrawing> lstDrawing)
        {
            if (lstDrawing == null || lstDrawing.Count < 1)
                return;

            try
            {
                //加载图纸信息数据文档
                var eleDoc = XElement.Load(DrawingDataFilePath);

                //获取根节点
                var eleRootNode = eleDoc.Element(CONST_ELE_NAME_DRAWINGS);

                //遍历图纸信息对象集，添加图纸信息到数据文档中
                foreach (var oDrawing in lstDrawing)
                {
                    eleRootNode.Add(_DrawingDataToEle(oDrawing));
                }

                //保存数据
                eleDoc.Save(DrawingDataFilePath);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 查询满足指定条件的图纸数据（这种算法的效率如何）
        /// </summary>
        /// <param name="lstConditionField">查询条件</param>
        /// <returns>图纸信息对象集</returns>
        public List<CDrawing> SearchDrawings(List<CField> lstConditionField)
        {
            var lstDrawing = new List<CDrawing>();

            //1.加载图纸信息数据文档
            var eleDoc = XElement.Load(DrawingDataFilePath);

            //2.获取所有图纸数据节点
            var lstDrawingNode = eleDoc.Elements(CONST_ELE_NAME_DRAWING);

            //3.遍历查询条件，查询匹配图纸数据
            foreach (var oConditionField in lstConditionField)
            {
                if (lstDrawingNode == null || lstDrawingNode.Count() < 1)
                    break;
                if (string.IsNullOrWhiteSpace(oConditionField.Value))
                    continue;

                //查询当前条件匹配的图纸数据
                lstDrawingNode = from oDrawingNode in lstDrawingNode
                                 where oDrawingNode.Attribute(CONST_DRAWING_ELE_ATTR_NAME_TYPE).Value.Trim().
                                                    Contains(oConditionField.Value)
                                 select oDrawingNode;
            }

            if (lstDrawingNode == null || lstDrawingNode.Count() < 1)
                return lstDrawing;

            //4.遍历图纸数据节点，封装为图纸信息对象添加至集合
            foreach (var oDrawingNode in lstDrawingNode)
            {
                lstDrawing.Add(_DrawingEleToData(oDrawingNode));
            }

            return lstDrawing;
        }

        #endregion

        #region Auxiliary Function

        /// <summary>
        /// 图纸信息对象转换为图纸数据元素
        /// </summary>
        /// <param name="oDrawing">图纸信息对象</param>
        /// <returns>图纸数据元素</returns>
        private XElement _DrawingDataToEle(CDrawing oDrawing)
        {
            var eleDrawingNode = new XElement(CONST_ELE_NAME_DRAWING,
                                              new XAttribute(CONST_DRAWING_ELE_ATTR_NAME_ID, oDrawing.ID),
                                              new XAttribute(CONST_DRAWING_ELE_ATTR_NAME_TOOLINGNO, oDrawing.ToolingNo),
                                              new XAttribute(CONST_DRAWING_ELE_ATTR_NAME_TYPE, oDrawing.Type),
                                              new XAttribute(CONST_DRAWING_ELE_ATTR_NAME_PARTNO, oDrawing.PartNo),
                                              new XAttribute(CONST_DRAWING_ELE_ATTR_NAME_PARTNAME, oDrawing.PartName),
                                              new XAttribute(CONST_DRAWING_ELE_ATTR_NAME_PROCESSNAME, oDrawing.ProcessName),
                                              new XAttribute(CONST_DRAWING_ELE_ATTR_NAME_FILEPATH, oDrawing.FilePath));

            return eleDrawingNode;
        }

        /// <summary>
        /// 图纸数据元素转换为图纸信息对象
        /// </summary>
        /// <param name="eleDrawingNode">图纸数据元素</param>
        /// <returns>图纸信息对象</returns>
        private CDrawing _DrawingEleToData(XElement eleDrawingNode)
        {
            var oRetDrawing = new CDrawing()
            {
                ID=eleDrawingNode.Attribute(CONST_DRAWING_ELE_ATTR_NAME_ID).Value.Trim(),
                ToolingNo = eleDrawingNode.Attribute(CONST_DRAWING_ELE_ATTR_NAME_TOOLINGNO).Value.Trim(),
                Type = eleDrawingNode.Attribute(CONST_DRAWING_ELE_ATTR_NAME_TYPE).Value.Trim(),
                PartNo = eleDrawingNode.Attribute(CONST_DRAWING_ELE_ATTR_NAME_PARTNO).Value.Trim(),
                PartName = eleDrawingNode.Attribute(CONST_DRAWING_ELE_ATTR_NAME_PARTNAME).Value.Trim(),
                ProcessName = eleDrawingNode.Attribute(CONST_DRAWING_ELE_ATTR_NAME_PROCESSNAME).Value.Trim(),
                FilePath = eleDrawingNode.Attribute(CONST_DRAWING_ELE_ATTR_NAME_FILEPATH).Value.Trim()
            };

            return oRetDrawing;
        }

        #endregion

    }
}
